﻿


using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using NetCore.ORM;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;

namespace NetCore
{
    public class CustomModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
          
            if (context.Metadata.ModelType != null&& context.Metadata.MetadataKind==ModelMetadataKind.Parameter && context.Metadata.ModelType.BaseType == typeof(EntityBase))
            {
                //if (AppHttpContext.Current.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
                //{
                 
                    return new BinderTypeModelBinder(typeof(CustomModelBinder));
                //}
            }
        
            return null;
        }


    }
    public class CustomModelBinder : IModelBinder
    {
      

        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            var modelName = bindingContext.ModelName;
            DbFactoryHelper action = new DbFactoryHelper(bindingContext.ModelMetadata.ModelType);
            var PrimaryValueResult = bindingContext.ValueProvider.GetValue(action.EntityMap.PrimaryKey);
            if (PrimaryValueResult == ValueProviderResult.None)
            {
                PrimaryValueResult = bindingContext.ValueProvider.GetValue("id");
            }
            object model =null;
            Dictionary<string, object> result = new Dictionary<string, object>();
            bool isUpdated = false;
            if (PrimaryValueResult != ValueProviderResult.None)
            {
                var value = PrimaryValueResult.FirstValue;
                Regex regex = new Regex("^([a-zA-Z0-9_\\-]+)Entity",RegexOptions.IgnoreCase);
                if (!string.IsNullOrWhiteSpace(value)&& regex.IsMatch(bindingContext.ModelMetadata.ModelType.Name))
                {
                    var primary= action.EntityMap.DbFields.Where(x => x.IsPrimaryKey).FirstOrDefault();
                    string keyName = regex.Match(bindingContext.ModelMetadata.ModelType.Name).Groups[1].Value;
                    if (AppHttpContext.ServiceInterface != null && AppHttpContext.ServiceInterface.ContainsKey(keyName))
                    {
                       dynamic iService= AppHttpContext.GetSerivce(AppHttpContext.ServiceInterface[keyName]);
                        if (iService != null)
                        {
                            if (primary.Identifier || primary.ColumnType.ToLower() == "int")
                            {
                                model = iService.GetById(value.ToInt());
                            }
                            else
                            {
                                model = iService.GetById(value);
                            }
                        }
                        
                      
                    }
                }
            }
            if (model == null)
            {
                model = ReflectionHelper.CreateInstance(bindingContext.ModelMetadata.ModelType);
            }
            else
            {
                isUpdated = true;
            }
            if (model != null)
            {
                foreach (var item in action.EntityMap.EntityFields)
                {
                    var fieldValue = bindingContext.ValueProvider.GetValue(item.Name);
                    if (fieldValue != ValueProviderResult.None)
                    {
                        Type fieldtype = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType;
                        if (AppHttpContext.IsPost)//表单提交时验证提交内容
                        {
                            var dbColumn= action.EntityMap.DbFields.Where(x => x.Name.Equals(item.Name)).FirstOrDefault() ;
                            string strError = "";
                            if (dbColumn!=null&&!VaildHelper.CheckInput(dbColumn.LocalName, dbColumn.AllowDBNull, string.IsNullOrWhiteSpace(dbColumn.VaildKey) ? "" : dbColumn.VaildKey, true,
                               (fieldValue != null ? fieldValue.ToString().Trim() : ""), 0, dbColumn.MaxLength, dbColumn.Min, dbColumn.Max, dbColumn.RegValidate, ref strError, dbColumn.ColumnType))
                            {
                                bindingContext.ModelState.AddModelError(item.Name, strError);
                            }
                        }
                        action.SetValue(model, item.Name, Convert.ChangeType(fieldValue.FirstValue.ToString().Trim(), fieldtype));
                    }
                }
                var baseEntity = model as EntityBase;
                baseEntity.IsUpdated = isUpdated;
            }
            
            bindingContext.Result = ModelBindingResult.Success(model);
            return Task.CompletedTask;
        }
    }

}
